package org.lonetree.tc.core;

import java.util.HashSet;
import java.util.Set;
import org.lonetree.tc.core.id.NaturaldentifiableItem;
import org.lonetree.tc.core.id.NumericalId;
import org.lonetree.tc.core.id.ValidatedIdentifier;

/**
 * Business class representing sections of university courses in the system.
 */
public final class Section extends NaturaldentifiableItem{
	
	private String professor;
	private Set<Book> books;
	
	protected Section(SectionId sectionId, String professor, Set<Book> books){
		super(sectionId);
		
		this.professor = professor;
		this.books = books;
		
		if(books == null)
			this.books = new HashSet<Book>();
	}
	
	/**
	 * Get the SectionId identifying the section.
	 *
	 * @return SectionId
	 */
	public SectionId getSectionId(){
		return (SectionId)getIdentifier();
	}

	/**
	 * Get the course that this section belongs to.
	 *
	 * @return Course
	 */
	public Course getParentCourse(){
		return getSectionId().getParentCourse();
	}
	
	/**
	 * Get the professor of the section.
	 *
	 * @return professor
	 */
	public String getProfessor(){
		return professor;
	}
	
	/**
	 * Get the books used by the section.
	 *
	 * @return books Set
	 */
	public Set<Book> getBooks(){
		return books;
	}
	
	/**
	 * Set the professor of the section.
	 *
	 * @param professor
	 */
	public void setProfessor(String professor){
		this.professor = professor;
	}
	
	protected String getIdentifierType(){
		return "sectionId";
	}
	
	/**
	 * ValidatedIdentifier representing a section ID (e.g. 001, 101, etc).
	 * SectionIds are unique identifiers for all Section objects since they
	 * are comprised of both the parent course's ID and a unique ID for sections
	 * within that particular course.
	 */
	public static class SectionId extends ValidatedIdentifier{

		private Course parentCourse;
		
		/**
		 * Create a SectionId encapsulating the passed section ID. Once created,
		 * the full SectionId becomes: 'courseId:sectionId' (where courseId is
		 * the parent course's ID).
		 *
		 * @param sectionId - the 3-number ID representing a section for a
		 * 					  course
		 * @param parentCourse - the course this section belongs to (cannot be
		 * 						 null)
		 * @throws ValidationException if the sectionId is greater than 999
		 * 							   (thus making it longer than 3 numbers)
		 * @throws NullPointerException if the parentCourse is null
		 */
		public SectionId(short sectionId, Course parentCourse) throws ValidationException{
			super(getCourseIdString(parentCourse) + ":" + sectionId);
			
			this.parentCourse = parentCourse;
		}
		
		private static String getCourseIdString(Course parentCourse){
			if(parentCourse == null)
				throw new NullPointerException("parentCourse cannot be null");
			
			return parentCourse.getCourseId().getCourseIdString();
		}

		@Override
		protected String validateAndFix(String identifier) throws ValidationException{
			String s = extractSection(identifier);
			try{
				long l = Long.parseLong(s);
				NumericalId numId = new NumericalId(l, 3){};
				return identifier.substring(0, 7) + ":" + numId.toString(); //this toString() is a bit of a hack because getIdentifierString() is not visible
			}
			catch(Exception e){
				throw new ValidationException(e);
			}
		}
		
		private static String extractSection(String identifier){
			return identifier.substring(identifier.lastIndexOf(':')+1);
		}
		
		/**
		 * Get the course this section belongs to.
		 *
		 * @return parent Course
		 */
		public Course getParentCourse(){
			return parentCourse;
		}
		
		/**
		 * Gets the numerical part of the sectionId.
		 *
		 * @return sectionId not including courseId
		 */
		public Long getSectionIdLong(){
			return new Long(extractSection(getIdentifierString()));
		}

		/**
		 * Gets the full sectionId.
		 *
		 * @return sectionId including prepended courseId and ":"
		 */
		public String getSectionIdString(){
			return getIdentifierString();
		}
	}
}
